<template>
  <div>
    <div ref="toolbar" class="quill-toolbar">
      <span class="ql-formats">
        <button class="ql-bold"></button>
        <button class="ql-italic"></button>
        <button class="ql-underline"></button>
        <button class="ql-strike"></button>
      </span>
      <span class="ql-formats">
        <select class="ql-size">
          <option value="small"></option>
          <option selected></option>
          <option value="large"></option>
          <option value="huge"></option>
        </select>
      </span>
      <span class="ql-formats">
        <select class="ql-color"></select>
        <select class="ql-background"></select>
      </span>
      <span class="ql-formats">
        <select class="ql-align"></select>
      </span>
      <span class="ql-formats">
        <button class="ql-clean"></button>
      </span>

      <span class="ql-formats">
        <button class="ql-link"></button>
        <button class="ql-image"></button>
        <button class="ql-video"></button>
      </span>

      <span class="ql-formats">
        <button type="button" title="LaTeX公式" @click="handleLaTex">
          <svg
            t="1583312327999"
            class="icon"
            viewBox="0 0 1024 1024"
            version="1.1"
            xmlns="http://www.w3.org/2000/svg"
            p-id="3689"
            width="16"
            height="16"
          >
            <path
              d="M630.894 739.529h152.537l38.134-76.268v152.537h-228.805v-127.659c78.129-33.666 133.469-117.457 133.469-215.547 0-127.734-93.92-227.762-209.738-227.762-115.855 0-209.737 99.952-209.737 227.762 0 98.091 55.303 181.882 133.469 215.547v127.659h-228.805v-152.537l38.134 76.268h152.537v-19.44c-111.832-39.549-190.671-135.48-190.671-247.499 0-147.473 136.561-266.939 305.073-266.939 168.475 0 305.073 119.467 305.073 266.939 0 112.019-78.876 207.876-190.671 247.499v19.44z"
              p-id="3690"
            />
          </svg>
        </button>
        <button type="button" title="WIRIS公式" @click="handleWiris">
          <svg
            t="1583312360308"
            class="icon"
            viewBox="0 0 1024 1024"
            version="1.1"
            xmlns="http://www.w3.org/2000/svg"
            p-id="3864"
            width="16"
            height="16"
          >
            <path
              d="M611.82976 512L300.4928 200.92928l545.2288-0.29696-0.04096-84.44928-667.36128 0.3584-0.04096 82.05312L492.34944 512 179.47648 824.60672l-1.19808 1.20832 0.04096 81.64352 667.36128 0.3584 0.04096-84.44928-545.2288-0.29696L611.82976 512z"
              p-id="3865"
            />
          </svg>
        </button>
      </span>
    </div>

    <div ref="editor" class="quill-editor" style="min-height: 200px"></div>

    <!-- 上传图片 -->
    <el-upload
      :show-file-list="false"
      :on-success="uploadSuccess"
      :before-upload="beforeUpload"
      :action="uploadApi"
      :headers="{ token }"
      class="quill-upload"
      accept="image/gif, image/jpeg, image/png"
    >
      <button ref="uploadButton" type="button"></button>
    </el-upload>

    <wiris ref="wiris" @change="wirisChange" @close="curTex = null" />
    <latex ref="latex" @change="latexChange" @close="curTex = null" />
  </div>
</template>

<script>
import Quill from 'quill'
import 'quill/dist/quill.snow.css'
import QuillImageDropAndPaste from 'quill-image-drop-and-paste'
import { uploadApi, uploadImg } from '@/api/common'
import { getToken } from '@/utils/auth'
import Wiris from './Wiris'
import Latex from './Latex'

export default {
  name: 'Editor',
  components: { Wiris, Latex },
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      quill: null,
      html: '',
      // 公式
      range: null,
      curTex: null,
      // 上传
      uploadApi,
      token: getToken()
    }
  },
  watch: {
    value(val) {
      if (!this.quill) return
      if (val && val !== this.html) {
        this.html = val
        this.quill.clipboard.dangerouslyPasteHTML(val)
      } else if (!val) {
        this.quill.setText('')
      }
    }
  },
  mounted() {
    const BlockEmbed = Quill.import('blots/embed')
    const ATTRIBUTES = ['src', 'class', 'alt']
    class ImageBlot extends BlockEmbed {
      static create(value) {
        const node = super.create(value)
        if (typeof value === 'string') {
          node.setAttribute('src', value)
        } else {
          node.setAttribute('src', value.src)
          if (value.class) node.setAttribute('class', value.class)
          if (value.alt) node.setAttribute('alt', value.alt)
        }
        return node
      }

      static formats(domNode) {
        return ATTRIBUTES.reduce((formats, attribute) => {
          if (domNode.hasAttribute(attribute)) {
            formats[attribute] = domNode.getAttribute(attribute)
          }
          return formats
        }, {})
      }

      static value(domNode) {
        return domNode.getAttribute('src')
      }

      format(name, value) {
        if (ATTRIBUTES.indexOf(name) > -1) {
          if (value) {
            this.domNode.setAttribute(name, value)
          } else {
            this.domNode.removeAttribute(name)
          }
        } else {
          super.format(name, value)
        }
      }
    }
    ImageBlot.blotName = 'image'
    ImageBlot.tagName = 'IMG'
    Quill.register(ImageBlot)
    Quill.register('modules/imageDropAndPaste', QuillImageDropAndPaste)

    this.quill = new Quill(this.$refs.editor, {
      modules: {
        toolbar: {
          container: this.$refs.toolbar,
          handlers: {
            image: () => this.$refs.uploadButton.click()
          }
        },
        imageDropAndPaste: {
          handler: (imageDataUrl, type, imageData) => {
            const filename = 'file.png'
            const file = imageData.toFile(filename)
            const formData = new FormData()
            formData.append('file', file)
            uploadImg(formData).then((res) => {
              this.insertImg({ src: res.data }, true)
            })
          }
        }
      },
      placeholder: '请输入...',
      theme: 'snow'
    })
    if (this.value) {
      this.quill.clipboard.dangerouslyPasteHTML(this.value)
    }
    const el = this.quill.container.firstChild
    this.quill.on('text-change', (delta, oldDelta, source) => {
      if (source === 'user') {
        this.html = el.innerHTML
        this.$emit('input', this.html)
      }
    })
    // 点击公式图片编辑
    el.addEventListener('click', (e) => {
      if (e.target.className === 'wiris-tex') {
        this.curTex = e.target
        this.$refs.wiris.open(e.target.alt)
      } else if (e.target.className === 'formula-tex') {
        this.curTex = e.target
        this.$refs.latex.open(e.target.alt)
      }
    })
  },
  methods: {
    // 插入图片
    insertImg(img, isUpload) {
      const quill = this.quill
      if (isUpload) {
        this.range = quill.getSelection()
      }
      if (this.range) {
        if (this.range.length > 0) {
          quill.deleteText(this.range.index, this.range.length)
        }
        quill.insertEmbed(this.range.index, 'image', img, 'user')
        quill.setSelection(this.range.index + 1)
        this.range = null
      } else {
        // eslint-disable-next-line
        console.log('User cursor is not in editor')
      }
    },
    // 上传图片
    beforeUpload(file) {
      const isLt3M = file.size / 1024 / 1024 < 3
      if (!isLt3M) {
        this.$message.error('上传图片大小不能超过 3MB!')
      }
      return isLt3M
    },
    uploadSuccess(res) {
      if (res.code !== 20000) {
        this.$message({
          message: res.msg,
          type: 'error'
        })
        return
      }
      this.insertImg({ src: res.data }, true)
    },
    // 插入公式
    handleWiris() {
      this.range = this.quill.getSelection()
      if (this.range) this.$refs.wiris.open()
    },
    wirisChange(alt) {
      const src = '//equation.kaoyanvip.cn/?mml=' + encodeURIComponent(alt)
      if (this.curTex) {
        this.curTex.src = src
        this.curTex.alt = alt
        this.curTex = null
      } else {
        this.insertImg({
          src,
          alt,
          class: 'wiris-tex'
        })
      }
    },
    handleLaTex() {
      this.range = this.quill.getSelection()
      if (this.range) this.$refs.latex.open()
    },
    latexChange(alt) {
      const src = '//equation.kaoyanvip.cn/?tex=' + encodeURIComponent(alt)
      if (this.curTex) {
        this.curTex.src = src
        this.curTex.alt = alt
        this.curTex = null
      } else {
        this.insertImg({
          src,
          alt,
          class: 'formula-tex'
        })
      }
    }
  }
}
</script>

<style scoped>
.quill-upload {
  display: none;
}
.quill-toolbar {
  line-height: normal;
}
</style>
